package org.example.service.impl;

import org.example.config.SmsConfig;
import org.example.service.SmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 短信服务实现
 */
@Service
@Slf4j
public class SmsServiceImpl implements SmsService {

	@Autowired
	private StringRedisTemplate stringRedisTemplate;

	@Autowired
	private SmsConfig smsConfig;

	// 使用全限定名，避免与 org.example.service.SmsService 同名冲突
	@Autowired
	private org.example.common.sms.SmsService kfSmsService;

	// 开发便捷：指定号码使用固定验证码（仅用于本地/测试联调）
	private static final java.util.Set<String> DEV_OVERRIDE_PHONES =
		new java.util.HashSet<>(java.util.Arrays.asList(
			"19558132574", // 原测试号
			"17856926342", // 企业端测试号
			"19156560856"  // 新增测试号，用于测试token类型隔离
		));
	private static final String DEV_OVERRIDE_CODE = "123456";

	/**
	 * 发送登录验证码（实现接口签名）
	 */
	@Override
	public boolean sendLoginCode(String phone, String type) {
		try {
			// 本地/测试便捷：指定号码直接下发固定验证码，不调用供应商
			if (DEV_OVERRIDE_PHONES.contains(phone)) {
				String redisKey = getRedisKey(phone, type);
				stringRedisTemplate.opsForValue().set(redisKey, DEV_OVERRIDE_CODE, 5, TimeUnit.MINUTES);
				log.info("[DEV-OVERRIDE] 直接下发固定验证码: {} -> {} [{}]", type, phone, DEV_OVERRIDE_CODE);
				return true;
			}

			String code = generateCode();
			String redisKey = getRedisKey(phone, type);
			stringRedisTemplate.opsForValue().set(redisKey, code, 5, TimeUnit.MINUTES);

			boolean success = sendTemplateSms(phone, code, "登录验证码");
			if (success) {
				log.info("登录验证码发送成功: {} -> {}", phone, code);
			} else {
				log.error("登录验证码发送失败: {} -> {}", phone, code);
			}
			return success;
		} catch (Exception e) {
			log.error("发送登录验证码异常: {} -> {}", type, phone, e);
			return false;
		}
	}

	/**
	 * 发送验证码
	 */
	@Override
	public boolean sendVerificationCode(String phone, String code, String type) {
		try {
			// 覆盖号码也允许写入指定code，便于联调
			if (DEV_OVERRIDE_PHONES.contains(phone)) {
				String redisKey = getRedisKey(phone, type);
				stringRedisTemplate.opsForValue().set(redisKey, code, 5, TimeUnit.MINUTES);
				log.info("[DEV-OVERRIDE] 覆盖号码写入验证码: {} -> {} [{}]", type, phone, code);
				return true;
			}

			String redisKey = getRedisKey(phone, type);
			stringRedisTemplate.opsForValue().set(redisKey, code, 5, TimeUnit.MINUTES);

			boolean success = sendTemplateSms(phone, code, "验证码");
			if (success) {
				log.info("验证码发送成功: {} -> {}", phone, code);
			} else {
				log.error("验证码发送失败: {} -> {}", phone, code);
			}
			return success;
		} catch (Exception e) {
			log.error("发送验证码异常: {}", phone, e);
			return false;
		}
	}

	/**
	 * 验证验证码
	 */
	@Override
	public boolean verifyCode(String phone, String code, String type) {
		try {
			String redisKey = getRedisKey(phone, type);
			String storedCode = stringRedisTemplate.opsForValue().get(redisKey);
			if (storedCode != null && storedCode.equals(code)) {
				stringRedisTemplate.delete(redisKey);
				log.info("验证码验证成功: {} -> {} [{}]", type, phone, code);
				return true;
			} else {
				log.warn("验证码验证失败: {} -> {} [{}], 存储的验证码: {}", type, phone, code, storedCode);
				return false;
			}
		} catch (Exception e) {
			log.error("验证验证码异常: {} -> {} [{}]", type, phone, code, e);
			return false;
		}
	}

	private String generateCode() {
		Random random = new Random();
		StringBuilder code = new StringBuilder();
		for (int i = 0; i < 6; i++) {
			code.append(random.nextInt(10));
		}
		return code.toString();
	}

	private String getRedisKey(String phone, String type) {
		// 企业端和用户端共享验证码，因为同一个手机号可能同时是企业端和用户端用户
		if ("enterprise".equals(type) || "user".equals(type)) {
			return String.format("sms:login:%s", phone);
		}
		return String.format("sms:%s:%s", type, phone);
	}

	private boolean sendTemplateSms(String phone, String code, String scene) {
		try {
			log.info("调用联麓短信服务: {} -> {} [{}]", scene, phone, code);
			log.info("配置信息: companyId={}, appId={}, templateId={}",
				smsConfig.getCompanyId(), smsConfig.getAppId(), smsConfig.getCodeTemplateId());

			boolean success = kfSmsService.sendSms(
				Arrays.asList(phone),
				smsConfig.getCodeTemplateId(),
				Arrays.asList(code)
			);
			return success;
		} catch (Exception e) {
			log.error("调用联麓短信服务异常: {} -> {} [{}]", scene, phone, code, e);
			return false;
		}
	}
}
